<script lang='ts' setup>
import { SiderMenuInfo, SiderMenuEnum } from '@/models/@types';
import { appContext } from '@/models/app.context';
import { onMounted, ref, watch } from 'vue';
import SiderItem from './SiderItem.vue'
import { Message } from '@arco-design/web-vue';
import { cloneDeep } from 'lodash-es'
import { appRef } from '@/models/app.ref';
import OperationBar from '@/components/chat/OperationBar.vue';


enum ActionEnum { Empty, Add, Edit, Remove, Default };
/**
 * 说明，公共侧边栏 API 如下
 * -- props --
 * menus        菜单列表  SiderMenuInfo[]
 * defaultUid   默认选择菜单的 uid    default：修改会话名
 * editTitle    编辑 弹窗的标题
 * removeDesc   确认删除的提示语      default：确认删除吗?
 *
 * -- emits --
 * add          发送      Parma： { type: SiderMenuEnum, parent: 有则是在合集下创建子集 }
 * clear        删除      Parma： null
 * clickItem    点击菜单  Parma： value: 菜单的uid
 * edit         编辑      Prama： { uid: 菜单的uid, label: 修改后的值 }
 * remove       删除      Parma： value: 菜单的uid
 * update       更新      parma : SiderMenuInfo[]
 *
 * -- slots --
 * null
 */
const props = withDefaults(defineProps<{
  menus: SiderMenuInfo[],
  defaultUid?: string,
  editTitle?: string,
  removeDesc?: string
}>(), {
  menus: [] as any,
  editTitle: '修改会话名',
  removeDesc: '确认删除吗?'
})
const emits = defineEmits(['add', 'clear', 'clickItem', 'edit', 'remove', 'update']);


watch(() => props.defaultUid, (newVal) => {
  if (newVal !== currMenu.value) {
    currMenu.value = newVal;
    onClickMenuItem(currMenu.value, ActionEnum.Default)
  } else if (!currMenu.value && !newVal) {
    onClickMenuItem(props.menus[0]?.uid, ActionEnum.Default)
  }
  currActiveKey.value = [props.menus?.find(val => val.childrens?.some(val => val.uid === currMenu.value))?.uid];
})
watch(() => props.menus, (newVal: SiderMenuInfo[]) => {
  if (!newVal?.length) {
    emits('add', { type: SiderMenuEnum.Leaf })
  }
  currActiveKey.value = [newVal.find(val => val.childrens?.some(val => val.uid === currMenu.value))?.uid];
})

const currMenu = ref('')
const currActiveKey = ref([])
const action = ref(ActionEnum.Empty);
let currMenuUid = '';

const selectSet = ref(new Set<string>());
const isEdit = ref(false);
onMounted(() => {

})

function onClickMenuItem(uid: string, type: ActionEnum = ActionEnum.Empty, label?: string) {
  if (!uid) return;
  currMenuUid = uid;
  action.value = type;
  if (type === ActionEnum.Default) {
    if (isEdit.value) {
      if (selectSet.value?.has(uid)) {
        selectSet.value.delete(uid);
      } else {
        selectSet.value.add(uid);
      }
    } else {
      currMenu.value = uid;
      appContext.system.data.viewWidth < 1000 ? (appRef.isOpen = false) : (appRef.isOpen = true);
      emits('clickItem', uid);
    }
  } else if (type === ActionEnum.Edit) {
    if (!label) {
      edit.value = props.menus.find(val => val.uid === uid)?.label || '';
    } else {
      edit.value = label;
    }
  } else if (type === ActionEnum.Remove) {
    emits('remove', uid)
  }
  checkSelectAll()
}

const edit = ref('');

/**
 * 检测是否选中全部
 */
function checkSelectAll() {
  let sum = 0;
  props.menus.forEach(value => {
    if (value.type === SiderMenuEnum.Group) {
      sum += value.childrens?.length | 0
    } else {
      sum++
    }
  })
  console.log('sum', sum)
  console.log('selectSet', selectSet.value.size)
  console.log('selectSet', selectSet.value)

  if (selectSet.value.size === sum) {
    selectAllFlag.value = true
  } else {
    selectAllFlag.value = false
  }
}

/**
 * 是否选中全部
 */
const selectAllFlag = ref(false)

/**
 * 是否选中全部
 * @param flag true 选中全部 false 取消全部选中
 */
function selectAll(flag: boolean) {
  const method = flag ? 'add' : 'delete'
  props.menus.map(value => {
    if (value.type === SiderMenuEnum.Group) {
      value.childrens?.forEach(value1 => {
        selectSet.value[method](value1.uid);
      })
    } else {
      selectSet.value[method](value.uid);
    }

  })
}

watch(() => selectSet.value, (value, oldValue, onCleanup) => {
  console.log(value)
  console.log(oldValue)
  console.log(onCleanup)
})

function onEdit(): void {
  console.log(edit.value);
  emits('edit', { uid: currMenuUid, label: edit.value })
  action.value = ActionEnum.Empty;
}


function onDelete(): void {
  if (isEdit.value) {
    selectSet.value.forEach(val => emits('remove', val));
  } else {
    emits('clear')
  }
  Message.success("操作成功");
}

let dragged;
const vDirective = {
  mounted: (source: HTMLElement, _binding: any) => {
    // source.addEventListener("drag", () => {
    //   const attributes = source.getAttributeNames();
    //   console.log("dragging", attributes);
    // });

    source.addEventListener("dragstart", (e) => {
      // // 保存被拖动元素的引用
      // dragged = event.target;
      // 设置为半透明
      source.classList.add("dragging");
      dragged = e.target;
    });
    source.addEventListener('dragenter', (e: DragEvent) => {
      e.preventDefault()
    })
    source.addEventListener('dragover', (e) => {
      e.preventDefault()
      // console.log('vDirective - dragover', e);
    })
    source.addEventListener("dragend", (e) => {
      // 拖动结束，重置透明度
      console.log('vDirective - dragend', e.target);
      if (!dragged) {
        // @ts-ignore
        e.target.classList.remove("dragover");
        return
      }
      const dparentId = dragged.getAttribute('parentId')
      const dchildId = dragged.getAttribute('childId')
      let cmuse = null, menus = cloneDeep(props.menus)
      if (dparentId) {
        const pmenus = menus.find(el => el.uid == dparentId)
        cmuse = pmenus.childrens.find(el => el.uid == dchildId)
        pmenus.childrens = pmenus.childrens.filter(el => el.uid != dchildId)
      } else {
        cmuse = menus.find(el => el.uid == dchildId)
        menus = menus.filter(el => el.uid != dchildId)
      }
      // @ts-ignore
      const tParentId = e.target.getAttribute('parentId')
      // @ts-ignore
      const tChildId = e.target.getAttribute('childId')

      if (tParentId) {
        const pmenus = menus.find(el => el.uid == tParentId)
        const targetIndex = pmenus.childrens.findIndex(el => el.uid == tChildId)
        pmenus.childrens.splice(targetIndex, 0, cmuse)
      } else {
        const targetIndex = menus.findIndex(el => el.uid == tChildId)
        menus.splice(targetIndex, 0, cmuse)
      }
      dragged.classList.remove("dragging");
      dragged = null
      emits('update', menus)
      console.log('vDirective', menus);
    });
  }
}

const vDroptarget = {
  mounted: (target: HTMLElement, _binding: any) => {
    target.addEventListener(
      "dragover",
      (event) => {
        // 阻止默认行为以允许放置
        event.preventDefault();
      },
      false,
    );

    target.addEventListener("dragenter", () => {
      // 在可拖动元素进入潜在的放置目标时高亮显示该目标
      // 在可拖动元素进入潜在的放置目标时高亮显示该目标
      if (target.classList.contains("dropzone")) {
        target.classList.add("dragover");
      }
    });

    target.addEventListener("dragleave", () => {
      // 在可拖动元素离开潜在放置目标元素时重置该目标的背景
      if (target.classList.contains("dropzone")) {
        target.classList.remove("dragover");
      }
    });

    target.addEventListener("drop", (event) => {
      // 阻止默认行为（会作为某些元素的链接打开）
      event.preventDefault();
      // 将被拖动元素移动到选定的目标元素中
      let menus = cloneDeep(props.menus)
      let cmuse = null
      if (dragged.getAttribute('parentId')) {
        // 移除
        const parentId = dragged.getAttribute('parentId')
        const childId = dragged.getAttribute('childId')
        if (parentId == childId) return;
        const pmenus = menus.find(el => el.uid == parentId)
        cmuse = pmenus.childrens.find(el => el.uid == childId)
        pmenus.childrens = pmenus.childrens.filter(el => el.uid != childId)

      } else {
        // 移除
        const childId = dragged.getAttribute('childId')
        cmuse = menus.find(el => el.uid == childId)
        menus = menus.filter(el => el.uid != childId)
      }
      // 插入
      const targetId = target.getAttribute('uid')
      const tMenus = menus.find(el => el.uid == targetId)
      if (tMenus.childrens) {
        tMenus.childrens.push(cmuse)
      } else {
        tMenus.childrens = [cmuse]
      }
      dragged.classList.remove("dragging")
      dragged = null
      // console.log('vDroptarget', menus);
      // update
      emits('update', menus)
    });
  }
}

/**
 * 是否选中选项触发change
 */
const handleSelectAllChange = (flag: boolean): void => {
  selectAllFlag.value = flag
  console.log('handleSelectAllChange ', flag)
  if (flag) {
    //全选
    selectAll(true)
  } else {
    //全不选
    selectAll(false)
  }
}



</script>
<template>
  <a-layout-sider class="slider flex-c animated" :class="{ 'fadeIn': appRef.isOpen }" v-show="appRef.isOpen">
    <OperationBar />
    <div class="sider-box flex-c">
      <div class="btns flex">
        <a-button class="btn" type="outline" @click="emits('add', { type: SiderMenuEnum.Leaf })">
          新会话
        </a-button>
        <a-button class="btn" type="outline" @click="emits('add', { type: SiderMenuEnum.Group })">
          新合集
        </a-button>
        <a-button type="outline" @click="isEdit = !isEdit">
          <template #icon>
            <icon-select-all />
          </template>
        </a-button>
      </div>
      <div class=" main scrollbar-none">
        <div class="menus">
          <a-collapse :bordered="false" v-model:active-key="currActiveKey" accordion>
            <div v-for="item in menus" :key="item.uid">
              <a-collapse-item v-droptarget :uid="item.uid" @click="null" :header="item.label"
                v-if="item.type === SiderMenuEnum.Group" :key="item.uid">
                <template #expand-icon="{ active }">
                  <icon-folder-delete size="17" v-if="active" />
                  <icon-folder size="17" v-else />
                </template>
                <template #extra>
                  <icon-plus class="icon" @click.stop="emits('add', { type: SiderMenuEnum.Leaf, parent: item.uid })" />
                  <icon-edit class="icon" @click.stop="onClickMenuItem(item.uid, ActionEnum.Edit)" />
                  <a-popconfirm :content="removeDesc" type="error" @ok="onClickMenuItem(item.uid, ActionEnum.Remove)">
                    <icon-delete class="icon" @click.stop="null" />
                  </a-popconfirm>
                </template>
                <div class="child" v-for="child in item.childrens" :key="child.uid">
                  <SiderItem v-directive draggable="true" :childId="child.uid" :parentId="item.uid" :isEdit="isEdit"
                    :checked="selectSet?.has(child.uid)" :is-curr="child.uid === currMenu" :item="child"
                    :removeDesc="removeDesc" @click-item="onClickMenuItem(child.uid, ActionEnum.Default)"
                    @edit="onClickMenuItem(child.uid, ActionEnum.Edit, child.label)"
                    @remove="onClickMenuItem(child.uid, ActionEnum.Remove)" />
                </div>
              </a-collapse-item>

              <SiderItem v-directive draggable="true" :childId="item.uid" :isEdit="isEdit"
                :checked="selectSet?.has(item.uid)" :is-curr="item.uid === currMenu" :item="item" :removeDesc="removeDesc"
                v-else @click="onClickMenuItem(item.uid, ActionEnum.Default)"
                @edit="onClickMenuItem(item.uid, ActionEnum.Edit, item.label)"
                @remove="onClickMenuItem(item.uid, ActionEnum.Remove)" />
            </div>
          </a-collapse>
        </div>
      </div>
      <div class="bottom flex">
        <div v-if="isEdit" style="width: 100%">
          <a-checkbox :model-value="selectAllFlag" style="margin-right: 6px;" @change="handleSelectAllChange">
            是否全选
          </a-checkbox>
        </div>
        <a-popconfirm content="确认删除吗？" type="error" @ok="onDelete" v-if="menus?.length">
          <a-button class="btn" long status="warning">
            <template #icon>
              <icon-delete />
            </template>
            <span>{{ isEdit ? '删除' : '清空' }}</span>
          </a-button>
        </a-popconfirm>
      </div>

    </div>

  </a-layout-sider>

  <a-modal :visible="action === ActionEnum.Edit" align-center @ok="onEdit" @cancel="action = ActionEnum.Empty"
    :title="editTitle" draggable width="auto">
    <a-input :style="{ width: '100%' }" placeholder="请输入新名称" v-model="edit" />
  </a-modal>
</template>
<style lang='scss' scoped>
.slider {
  border-left: 1px solid var(--color-neutral-4);
  max-width: 100%;
  height: 100%;
  overflow: hidden;
  width: 300px !important;

  .sider-box {
    width: 100%;
    height: 100%;
    flex: 1;
    overflow: hidden;
    justify-content: space-between;

    .main {
      flex: 1;
      overflow: auto;

      .icon {
        margin-right: 5px;
      }

      ::v-deep .arco-collapse-item-header {
        padding-right: 13px;
        padding-left: 34px;
        margin: 0 10px;
      }

      .child {
        width: 100%;
        margin: 0 -15px;
        width: 118%;
        transform: translateX(-6%);

        &:first-child {
          margin-top: -15px;
        }

        &:last-child {
          margin-bottom: -15px;
        }
      }
    }

    .selectedAll {
      padding: 10px 15px;
      margin: 10px 20px;
      background: #F2F3F5;
    }

    .btns {
      width: calc(100% - 40px);
      margin: 10px 20px;
      overflow: hidden;
      justify-content: space-between;

      .btn {
        flex: 1;
        margin-right: 6px;
      }
    }

    .bottom {
      width: 100%;
      padding: 10px;

      .btn {
        width: 100%;
      }
    }
  }

  .collapsed {

    cursor: pointer;
    z-index: 99;
    height: 35px;
    width: 60px;
    justify-content: center;

    svg {
      height: 100%;
    }
  }

  .dropzone {
    width: 200px;
    height: 20px;
    background: blueviolet;
    margin: 10px;
    padding: 10px;
  }

  .dropzone.dragover {
    background-color: purple;
  }

  .dragging {
    opacity: 0.5;
  }

}

@media screen and (max-width :1000px) {
  .slider {
    width: 100% !important;
  }
}

::v-deep {
  .arco-layout-sider-children {
    width: 100%;
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
}
</style>
